package robocup.component.situations;

import java.util.LinkedList;

import robocup.component.Prophet;
import robocup.component.SConf;
import robocup.component.WorldModel;
import robocup.component.ControllerNumbers.PLAY_MODE;
import robocup.component.ControllerNumbers.STAMINA_LEVEL;
import robocup.component.ControllerNumbers.TEAM;
import robocup.component.actionfactories.BasicActionFactory;
import robocup.component.actions.Action;
import robocup.component.actions.CatchAction;
import robocup.component.actions.DashAction;
import robocup.component.actions.KickAction;
import robocup.component.actions.TurnAction;
import robocup.component.geometry.Vektor;
import robocup.component.geometry.analysers.ReachableArea;
import robocup.component.worldobjects.Ball;
import robocup.component.worldobjects.Line;
import robocup.component.worldobjects.Player;
import robocup.component.worldobjects.Player.RELATIVE;

/**
 * The best action of the goalie is calculated here.
 * 
 * @author Thomas Karbe
 * 
 */
public class GoalkeeperSituation
    extends Situation {

  private static final String       DEFENSIVE             = "defensive";

  private static final String       INTERCEPTION          = "interception";

  private static final String       CATCH                 = "catch";

  private static final String       KICK                  = "kick";

  private static final String       INTERCEPT_GOAL_BALL   = "intercept goal ball";

  private static final String       STANDARD              = "standard";

  private static final double CATCH_SECURITY_DIST   = 0.05;

  private static final double KICK_SECURITY_DIST    = 0.05;

  private static final int    INTERCEPTION_SECURITY = 2;

  private static final double PASS_BENEFIT          = 0.2;

  private static final double DANGEROUS_DIST        = 28.0;

  private static final double IS_DEFENDED_DIST      = 4.0;

  private static final double GOOD_POS_BUFFER       = 1.0;

  private static final Vektor ANCHOR                = new Vektor(Vektor.XY, 0,
                                                        -57);

  private final boolean             debug                 = false;

  private final boolean             debugDef              = false;

  SConf                       sConf                 = null;

  PLAY_MODE                   playmode              = null;

  Player                      keeperRef             = null;

  Ball                        ballRef               = null;

  Player                      fastOpp               = null;

  Vektor                      enemyPos              = null;

  Vektor                      bestDefPos            = Vektor.getDummyInstance();

  int                         fastOppIT             = 0;

  Line                        dummyLine1            = new Line(Vektor
                                                        .getDummyInstance(),
                                                        Vektor
                                                            .getDummyInstance());

  Line                        dummyLine2            = new Line(Vektor
                                                        .getDummyInstance(),
                                                        Vektor
                                                            .getDummyInstance());

  Line                        shortLine             = new Line(Vektor
                                                        .getDummyInstance(),
                                                        Vektor
                                                            .getDummyInstance());

  Line                        longLine              = new Line(Vektor
                                                        .getDummyInstance(),
                                                        Vektor
                                                            .getDummyInstance());

  Line                        middleLine            = new Line(Vektor
                                                        .getDummyInstance(),
                                                        Vektor
                                                            .getDummyInstance());

  Line                        defenseLine           = new Line(Vektor
                                                        .getDummyInstance(),
                                                        Vektor
                                                            .getDummyInstance());

  Vektor                      dummyVektor           = Vektor.getDummyInstance();

  Vektor                      dummyVektor1          = Vektor.getDummyInstance();

  Vektor                      dummyVektor2          = Vektor.getDummyInstance();

  Vektor                      dummyVektor3          = Vektor.getDummyInstance();

  Vektor                      dummyVektor4          = Vektor.getDummyInstance();

  Ball                        dummyBall1            = Ball.getDummyInstance();

  Ball                        dummyBall2            = Ball.getDummyInstance();

  Player                      dummyPlayer1          = Player.getDummyInstance();

  ReachableArea               ra                    = new ReachableArea();

  Vektor                      leftPostRef           = Vektor.getDummyInstance();

  Vektor                      rightPostRef          = Vektor.getDummyInstance();

  Vektor                      shortPost             = Vektor.getDummyInstance();

  Vektor                      longPost              = Vektor.getDummyInstance();

  DashAction                  dashAction            = new DashAction(0);

  TurnAction                  turnAction            = new TurnAction(0);

  boolean                     ballGoesOut           = false;

  private boolean shouldTackle;

  /**
   * Creates a new GoalkeeperSituation - a situation which calculates how to
   * behave as goalie in different situations
   * 
   * @param world -
   *          the current world-model
   * @param movements -
   *          a generic movement model
   * @param _prophet -
   *          the parent object of this
   */
  public GoalkeeperSituation(
      final WorldModel world,
      final Movements movements,
      final Prophet prophet) {

    super(world, prophet, movements);
    this.update();
  }

  @Override
  protected void update() {

    this.sConf = SConf.getInstance();
    this.shouldTackle= false;
    this.playmode = this.getWorld().getPlayMode();
    this.keeperRef = this.getWorld().getSelfRef();
//    if (!this.keeperRef.isGoalie()) {
//      System.out.println("GoalkeeperSituation is used by invalid player");
//      System.out.println("DONT USE IT WITH " + keeperRef);
//    }
    this.ballRef = this.getWorld().getBallRef();
    this.fastOpp = this.prophet.getFastestEnemyToBall();
    this.fastOppIT = this.fastOpp == null ? -1 : this.prophet
        .getInterceptionTime(this.fastOpp.getNumber(), false);
    this.leftPostRef = this.sConf.GOAL_POST_LEFT_OWN;
    this.rightPostRef = this.sConf.GOAL_POST_RIGHT_OWN;
    this.ballGoesOut = this.prophet.ballOutBeforeIntercept();

    this.calculateBestAction();
    super.update();
  }

  private void calculateBestAction() {

    long time = System.currentTimeMillis();
    this.benefit = 1.;
    this.bestAction= null;
    if (this.debug) {
      System.out.println("\n" + this.getWorld().getCycleAndPlayerString());
    }
    if (this.playmode == PLAY_MODE.PLAY_ON) {
      if (this.canCatch()) {
        this.bestAction = this.catchBallAction();
        this.subStateString = GoalkeeperSituation.CATCH;
        if (this.debug) {
          System.out.println("catch ball " + this.bestAction);
        }
      }// end can catch
      else {// cannot catch
        if (this.canKick()) {
          this.bestAction = this.kickBallAction();
          this.subStateString = GoalkeeperSituation.KICK;
          if (this.debug) {
            System.out.println("kick ball " + this.bestAction);
          }
        }// end can kick
        else {// cannot kick
          if (this.fastestToBall() && !this.ballGoesOut) {
            this.bestAction = this.goForInterceptAction();
            this.subStateString = GoalkeeperSituation.INTERCEPTION;
            if (this.debug) {
              System.out
                  .println("fastest && ball not out --> intercept " + this.bestAction);
            }
          }// end fastest to intercept
          else { // not fastest to intercept
            if (this.ballInDangerousDistance() && !this.ballGoesOut) {
              if (this.teamIsFastToBall()) {
                this.bestAction = this.defensivePositioningAction();
                this.subStateString = GoalkeeperSituation.DEFENSIVE;
                if (this.debug) {
                  System.out
                      .println("We are fastest --> defensive " + this.bestAction);
                }
              }// end team has ball
              else {// team is not fastest to ball
                if (this.attackerIsBlocked()) {
                  this.bestAction = this.defensivePositioningAction();
                  this.subStateString = GoalkeeperSituation.DEFENSIVE;
                  if (this.debug) {
                    System.out
                        .println("attacker blocked --> defensive " + this.bestAction);
                  }
                }// end attacker is blocked
                else {// attacker isn't blocked
                  if (Math.abs(this.ballRef.getPosition().x) < 7) {
                    if (this.attackerCanKick()) {
                      this.bestAction = this.defensivePositioningAction();
                      this.subStateString = GoalkeeperSituation.DEFENSIVE;
                      if (this.debug) {
                        System.out
                            .println("attacker can kick --> kick danger action " + this.bestAction);
                      }
                    } // end attacker can kick
                    else {// attacker cannot kick
                      this.bestAction = this.defensivePositioningAction();
                      this.subStateString = GoalkeeperSituation.DEFENSIVE;
                      if (this.debug) {
                        System.out
                            .println("attacker cannot kick --> offensive positioning " + this.bestAction);
                      }
                    }// end attacker cannot kick
                  } // end ball in front of goal
                  else { // ball at side
                    this.bestAction = this.defensivePositioningAction();
                    this.subStateString = GoalkeeperSituation.DEFENSIVE;
                    if (this.debug) {
                      System.out
                          .println("ball at side --> defensive positioning " + this.bestAction);
                    }
                  }
                }// end attacker isn't blocked
              }// end team is not fastest to ball
            }// end ball in dangerous distance
            else if (this.ballInDangerousDistance() && this.ballGoesOut) {
              // possibly a goal
              if (this.ballGoesToGoal()) {
                this.bestAction = this.interceptGoalBallAction();
                this.subStateString = GoalkeeperSituation.INTERCEPT_GOAL_BALL;
                if (this.debug) {
                  System.out
                      .println("possible goal shot --> intercept " + this.bestAction);
                }
              }
              else {
                this.bestAction = this.defensivePositioningAction();
                this.subStateString = GoalkeeperSituation.DEFENSIVE;
                if (this.debug) {
                  System.out
                      .println("ball goes out --> defensive positioning " + this.bestAction);
                }
              }
            }
            else {// ball not in dangerous distance
              this.bestAction = this.defensivePositioningAction();
              this.subStateString = GoalkeeperSituation.DEFENSIVE;
              if (this.debug) {
                System.out
                    .println("ball away --> defensive positioning " + this.bestAction);
              }
            }// end ball not in dangerous distance
          } // end not fastest to intercept
        }// end cannot kick
      }// end cannot catch
    }// end play_on
    else {// playmode is not play_on
      if (PLAY_MODE.META_STANDARD_OWN.contains(this.playmode)) { // our
        // standard
        if (this.goalieStandard()) {
          this.bestAction = this.myStandardAction();
          this.subStateString = GoalkeeperSituation.STANDARD;
          if (this.debug) {
            System.out.println("goalie standard " + this.bestAction);
          }
        }// end standard of goalie
        else {// no standard of goalie
          this.bestAction = this.defensivePositioningAction();
          this.subStateString = GoalkeeperSituation.DEFENSIVE;
          if (this.debug) {
            System.out.println("other standard " + this.bestAction);
          }
        }// end ball not in penalty
      }// end our standard
      else {// not our standard
        if (this.playmode == PLAY_MODE.GOAL_OTHER) {
          this.bestAction = BasicActionFactory.turnBodyToPoint(this.keeperRef,
              this.sConf.GOAL_POS_OTHER);
          this.benefit = 1;
        }
        else {
          this.bestAction = this.defensivePositioningAction();
          if (this.debug) {
            System.out.println("opp standard " + this.bestAction);
          }
        }
      }// end not our standard
    }// end not play_on
    time = System.currentTimeMillis() - time;
    if (this.debug) {
      System.out.println("time: " + time);
    }
    
    if (this.bestAction == null) {
      if (this.debug) {
        System.out.println(getWorld().getCycleAndPlayerString()+" no bestAction for Goalie");
      }
    }
  }

  /**
   * @return true if ball close enough and in our penalty
   */
  private boolean canCatch() {

    if (this.ballRef.getAge(this.getWorld().getBodyCycle()) > 2) {
      return false;
    }
    if (!this.getWorld().inOwnPenaltyArea(this.ballRef)) {
      return false;
    }
    boolean importantCatch= false;
    boolean shouldTackle= false;

    if(getProphet().inPossessionOfBall() == TEAM.WE){
    	shouldTackle = false;
    }
    if (this.getProphet().ballWillGoIntoOwnGoal()) {
      importantCatch= true;
      if (shouldTackle) {
        importantCatch = false;
      }
    }
    if (this.keeperRef.getCatchDistance() - (!importantCatch?GoalkeeperSituation.CATCH_SECURITY_DIST:0) < this.ballRef
        .getDistance(this.keeperRef)) {
      this.shouldTackle=shouldTackle;
      return false;
    }
    return true;
  }
  
  public boolean shouldTackle() {

    if (!this.wasUpdated()) {
      this.update();
    }

    return this.shouldTackle;
  }

  /**
   * @return true if the goalie can kick the ball
   */
  private boolean canKick() {

    if (this.ballRef.getAge(this.getWorld().getBodyCycle()) > 2) {
      return false;
    }
    if (this.keeperRef.getKickDistance() - GoalkeeperSituation.KICK_SECURITY_DIST < this.keeperRef
        .getDistance(this.ballRef)) {
      return false;
    }
    return true;
  }

  /**
   * @return true if I am fastest to ball
   */
  private boolean fastestToBall() {

    return this.prophet.iAmFastestToBall() && this.getWorld().getAge(
        this.ballRef) <= 2;
  }

  /**
   * @return true if the ball is closer to goal than the given dangerous
   *         distance
   */
  private boolean ballInDangerousDistance() {

    if (this.ballRef.getAge(this.getWorld().getBodyCycle()) > 3) {
      return false;
    }
    final Vektor pos = this.ballRef.getPosition();
    if (Math.abs(pos.y + this.sConf.half_length) < GoalkeeperSituation.DANGEROUS_DIST) {
      if (Math.abs(pos.x) < this.sConf.half_goal_width) {
        return true;
      }
      if (pos.getDistance(this.sConf.GOAL_POST_LEFT_OWN) < GoalkeeperSituation.DANGEROUS_DIST) {
        return true;
      }
      if (pos.getDistance(this.sConf.GOAL_POST_RIGHT_OWN) < GoalkeeperSituation.DANGEROUS_DIST) {
        return true;
      }
    }
    return false;
  }

  /**
   * @return true if a teammate is fastest to ball
   */
  private boolean teamIsFastToBall() {

    if (this.ballRef.getAge(this.getWorld().getBodyCycle()) > 3) {
      return false;
    }
    if (this.fastOppIT > this.prophet.getInterceptionTime() + GoalkeeperSituation.INTERCEPTION_SECURITY || this.fastOppIT == -1) {
      return true;
    }
    return false;
  }

  /**
   * @return true if the attacker has to pass a defender
   */
  private boolean attackerIsBlocked() {

    if (this.fastOpp != null) {
      this.dummyVektor1.x = 10;
      this.dummyVektor1.y = -52.5;
      this.dummyVektor2.x = -10;
      this.dummyVektor2.y = -52.5;
      double angle1 = this.fastOpp.getAngleTo(this.dummyVektor1);
      double angle2 = this.fastOpp.getAngleTo(this.dummyVektor2);
      if (angle1 < 0) {
        angle1 += 360;
      }
      if (angle2 < 0) {
        angle2 += 360;
      }
      final double middleAngle = Vektor.normalize((angle1 + angle2) / 2);
      final double dev = Math.abs(angle1 - middleAngle);
      final LinkedList<Player> team = this.getWorld().getTeammates(
          this.fastOpp.getPosition(), middleAngle, dev,
          GoalkeeperSituation.IS_DEFENDED_DIST);
      int index = -1;
      for (final Player p : team) {
        if (p.isGoalie()) {
          index = team.indexOf(p);
        }
      }
      if (index > -1) {
        team.remove(index);
      }
      if (team.size() < 1) {
        return false;
      }
      return true;
    }
    return true;
  }

  /**
   * @return true if the attacker can kick
   */
  private boolean attackerCanKick() {

    return this.getWorld().ballCanBeKickedByOpponent();
  }

  /**
   * @return true if the goalie has to make the standard
   */
  private boolean goalieStandard() {

    if (this.playmode == PLAY_MODE.FREE_KICK_OWN || PLAY_MODE.GOAL_KICK_OWN == this.playmode) {
      return true;
    }
    return false;
  }

  /**
   * if passing has a better value, the result is unused otherwise we hold the
   * ball, or kick it out (in case of near opponents)
   * 
   * @return a kick-action
   */
  private Action kickBallAction() {

    if (this.prophet.getPassBenefit() <= GoalkeeperSituation.PASS_BENEFIT) {// calculate
                                                                            // better
                                                                            // kick
      if (this.fastOppIT < 5 && this.fastOppIT != -1) {
        final Vektor kickPos = this.ballRef.getPosition().x > 0 ? this.sConf.CORNER_RIGHT_OWN : this.sConf.CORNER_LEFT_OWN;
        final double kickAngle = this.ballRef.getAngleTo(kickPos);
        this.benefit = 1.0;
        return new KickAction(100, kickAngle);
      }
      this.dummyVektor.setVektor(0.8, this.keeperRef.getBodyDir());
      final Vektor kickPos = this.getWorld().getMyNextPosition()
          .add(this.dummyVektor);
      KickAction kick = BasicActionFactory.kickInTime(this.keeperRef,
          this.ballRef, kickPos, 1, 0.2);
      if (kick == null) {
        final double kickAngle = Vektor
            .normalize(this.ballRef.getSpeed().getAngle() + 180);
        kick = new KickAction(100, kickAngle);
      }
      this.benefit = GoalkeeperSituation.PASS_BENEFIT;
      return kick;
    }// end calculate better kick
    this.benefit = GoalkeeperSituation.PASS_BENEFIT;
    return this.prophet.getPassAction();
  }

  /**
   * makes the goalie catch the ball
   * 
   * @return the needed catch-action
   */
  private Action catchBallAction() {

    final double angleToBall = this.getWorld().getSelfRef().getAngleRel(this.ballRef,
        RELATIVE.TO_BODY);
    this.benefit = 1.0;
    return new CatchAction(angleToBall);
  }

  /**
   * @return the best action to intercept the ball
   */
  private Action goForInterceptAction() {

    // System.out.println("\n"+getWorld().getCycleAndPlayerString()+"
    // intercept
    // Ball");
    return this.prophet.getMyNextInterceptAction();
  }

  /**
   * @return an action that moves the goalie to an defensive position near the
   *         goal
   */
  private Action defensivePositioningAction() {

    // System.out.println("\n"+getWorld().getCycleAndPlayerString()+"
    // defpos");
    this.benefit = 1.0;
    // calculate good pos in goal
    this.calculateDefensivePosition();

    if (this.debugDef) {
      System.out.println("bestDefPos: " + this.bestDefPos);
    }

    this.ra.setArea(1, 0, this.keeperRef, GoalkeeperSituation.GOOD_POS_BUFFER);
    final Vektor lookPos = Vektor.getDummyInstance();
    lookPos.copy(this.bestDefPos);

    if (this.ballRef.getPosition().x < this.bestDefPos.x) {
      lookPos.x = this.bestDefPos.x - 3;
    }
    else {
      lookPos.x = this.bestDefPos.x + 3;
    }

    if (this.debugDef) {
      System.out.println("turnTo: " + lookPos);
    }

    final Action a = this.ra.getFirstMoveToPos(this.bestDefPos,
        GoalkeeperSituation.GOOD_POS_BUFFER, 15, true, -1, this.ballRef
            .getPosition(), lookPos);
    if (this.ballRef.getDistance(this.sConf.GOAL_POS_OWN) > 30) {
      this.keeperRef.correctDashPower(a, STAMINA_LEVEL.MAX);
      if (this.debugDef) {
        System.out.println("stamina max");
      }
    }
    else {
      this.keeperRef.correctDashPower(a, STAMINA_LEVEL.LOW);
      if (this.debugDef) {
        System.out.println("stamina low");
      }
    }

    return a;
  }

  /**
   * @return uses goalie kick in state
   */
  private Action myStandardAction() {

    this.benefit = 0.001;
    return null;
  }

  private void calculateDefensivePosition() {

    this.dummyLine1.copyPoint1(GoalkeeperSituation.ANCHOR);
    this.dummyLine1.copyPoint2(this.ballRef.getPosition());
    if (this.ballRef.getPosition().y < -50) {
      if (this.ballRef.getPosition().x < this.sConf.GOAL_POST_LEFT_OWN.x - 3) {
        if (this.debugDef) {
          System.out.println("ball close and at side");
        }
        this.bestDefPos.x = this.sConf.GOAL_POST_LEFT_OWN.x + 0.75;
        this.bestDefPos.y = this.sConf.GOAL_POST_LEFT_OWN.y + 1.5;
      }
      else if (this.ballRef.getPosition().x > this.sConf.GOAL_POST_RIGHT_OWN.x + 3) {
        if (this.debugDef) {
          System.out.println("ball close and at side");
        }
        this.bestDefPos.x = this.sConf.GOAL_POST_RIGHT_OWN.x - 0.75;
        this.bestDefPos.y = this.sConf.GOAL_POST_RIGHT_OWN.y + 1.5;
      }
      else {
        if (this.debugDef) {
          System.out.println("ball close and in front --> go to ball");
        }
        this.bestDefPos.copy(this.ballRef.getPosition());
      }
    }
    else {
      // more than 2.5 m from goal
      try {
        this.bestDefPos.copy(this.dummyLine1.getPointWithYValue(-50));
        if (this.debugDef) {
          System.out.println("pos on 50-Line: " + this.bestDefPos);
        }
      }
      catch (final Exception e) {
        if (this.debugDef) {
          System.out.println("exception pos (-50;0)");
        }
        this.bestDefPos.x = 0;
        this.bestDefPos.y = -50;
        e.printStackTrace();
      }
      if (this.fastOpp != null) {
        if (this.fastOpp.getPosition().y < -37.5 && Math.abs(this.fastOpp
            .getPosition().x) < 9) {
          if (this.debugDef) {
            System.out.println("fastOpp in front -> move BestPos");
          }
          this.dummyVektor2.copy(this.fastOpp.getPosition());
          this.dummyVektor1.setVektor(2, this.fastOpp.getBodyDir());
          this.dummyVektor2.addToThis(this.dummyVektor1);
          final Line l = new Line(this.fastOpp.getPosition(), this.dummyVektor2);
          Vektor v= l.getPointWithYValue(-50);
          if (v==null) {
            this.dummyVektor2.setX(fastOpp.getPosition().x);
            this.dummyVektor2.setY(-50);
          }
          else {
            this.dummyVektor2.copy(l.getPointWithYValue(-50));
          }
          if (Math.abs(this.dummyVektor2.x) > 6) {
            if (this.dummyVektor2.x > 0) {
              this.dummyVektor2.x = 6;
            }
            else {
              this.dummyVektor2.x = -6;
            }
          }
          if (this.debugDef) {
            System.out.println("movePos: " + this.dummyVektor2);
          }
          this.bestDefPos.x = (5 * this.bestDefPos.x + this.dummyVektor2.x) / 6;
        }
      }
      if (this.bestDefPos.x > 6.5) {
        this.bestDefPos.x = 6.5;
        this.bestDefPos.y = -51;
      }
      else if (this.bestDefPos.x < -6.5) {
        this.bestDefPos.x = -6.5;
        this.bestDefPos.y = -51;
      }
    }
    if (this.ballRef.getPosition().x < 0) {
      final double ballCycles = (this.ballRef
          .getDistance(this.sConf.GOAL_POST_LEFT_OWN) - 2.7) / 3.;
      if (Math.abs(this.bestDefPos.x - this.sConf.GOAL_POST_LEFT_OWN.x) - 0.5 < ballCycles) {
        if (this.debugDef) {
          System.out
              .println(this.getWorld().getCycleAndPlayerString() + " ballCycles :" + ballCycles);
        }
        this.bestDefPos.x = this.sConf.GOAL_POST_LEFT_OWN.x - 0.5 + (ballCycles * 0.8);
        if (this.debugDef) {
          System.out.println("too close to left post " + this.bestDefPos.x);
        }
        if (this.bestDefPos.x > 0) {
          this.bestDefPos.x = 0;
        }
      }
    }
    if (this.ballRef.getPosition().x > 0) {
      final double ballCycles = (this.ballRef
          .getDistance(this.sConf.GOAL_POST_RIGHT_OWN) - 2.7) / 3.;
      if (Math.abs(this.bestDefPos.x - this.sConf.GOAL_POST_RIGHT_OWN.x) - 0.5 < ballCycles) {
        if (this.debugDef) {
          System.out
              .println(this.getWorld().getCycleAndPlayerString() + " ballCycles :" + ballCycles);
        }
        this.bestDefPos.x = this.sConf.GOAL_POST_RIGHT_OWN.x + 0.5 - (ballCycles * 0.8);
        if (this.debugDef) {
          System.out.println("too close to right post " + this.bestDefPos.x);
        }
        if (this.bestDefPos.x < 0) {
          this.bestDefPos.x = 0;
        }
      }
    }
  }

  /**
   * Calculates the needed turn-argument to reach a given turn-angle.
   * 
   * @param a
   * @param p
   * @return the needed argument
   */
  public static double getTurnArg(final double a,
      final Player p) {

    return a * (1 + p.getPConf().INERTIA_MOMENT * p.getSpeed().getLength());
  }

  /**
   * Calculates the resulting turn-angle after using argument a.
   * 
   * @param a
   * @param p
   * @return the resulting turn angle
   */
  public static double getTurnFromArg(final double a,
      final Player p) {

    return a / (1 + p.getPConf().INERTIA_MOMENT * p.getSpeed().getLength());
  }

  private boolean ballGoesToGoal() {

    final Vektor ballpos = this.getWorld().getBallRef().getPosition();
    final Vektor ballspeed = this.getWorld().getBallRef().getSpeed();
    if (Math.abs(ballspeed.getAngle()) <= 91) {
      return false;
    }
    this.dummyLine1.copyPoint1(ballpos);
    this.dummyLine1.copyPoint2(ballpos.add(ballspeed));
    final Vektor outPoint = this.dummyLine1.getPointWithYValue(-52.5);
    if (Math.abs(outPoint.x) < 8) {
      return true;
    }
    return false;
  }

  private Action interceptGoalBallAction() {

    this.ra.setArea(1, 0, this.getWorld().getSelfRef(), this.getWorld()
        .getSelfRef().getCatchDistance());
    this.dummyLine1.copyPoint1(this.ballRef.getPosition());
    this.dummyLine1.copyPoint2(this.ballRef.getPosition().add(
        this.ballRef.getSpeed()));
    this.dummyLine2.copyPoint1(this.keeperRef.getPosition());
    this.dummyVektor.setVektor(10, this.getWorld().getBodyAngle());
    this.dummyLine2.copyPoint2(this.keeperRef.getPosition().add(
        this.dummyVektor));
    boolean dash = true;
    final Vektor outPoint = this.dummyLine1.getPointWithYValue(-52.5);
    final Vektor dashPoint = this.dummyLine1
        .getIntersectionPointWithLine(this.dummyLine2);
    if (dashPoint.getDistance(outPoint) > this.ballRef.getDistance(outPoint)) {
      dash = false;
    }
    double dashTime = this.ballRef.getDistance(dashPoint) / this.ballRef
        .getSpeed().getLength();
    double outTime = this.ballRef.getDistance(outPoint) / this.ballRef
        .getSpeed().getLength();
    if (dash) {
      dashTime -= this.ra.getMovesToPos(dashPoint, true, null).size();
      outTime -= this.ra.getMovesToPos(outPoint, true, null).size();
      if (outTime > dashTime) {
        dash = false;
      }
    }
    if (dash) {
      return this.ra.getFirstMoveToPos(dashPoint, this.keeperRef
          .getCatchDistance(), 15, true, -1, null, null);
    }
    else {
      return this.ra.getFirstMoveToPos(outPoint, this.keeperRef
          .getCatchDistance(), 15, true, -1, null, null);
    }
  }
}
